package cz.vse.po1715.lode.net.server;

import cz.vse.po1715.lode.net.obecne.FrontaUdálostí;
import cz.vse.po1715.lode.net.obecne.IHerniUdalost;
import java.util.logging.*;

/*******************************************************************************
 * Instance třídy {@code SprávceUdálostí} představují fond vláken propojených
 * s příchozí blokující frontou (návrhový vzor Wrap) herních událostí
 *
 * @author    Dominik KOSTKA
 * @version   0.00.000
 */
public abstract class ASprávceUdálostí implements Runnable, ISprávceUdálostí
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================

    /** délka spánku vlákna v milisekundách mezi zpracováním běhů*/
    protected static final long WORKER_SPÁNEK_MILIS = 10;
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** logger */
    protected Logger log;

    /** fronta příchozích událostí*/
    protected FrontaUdálostí vstupníFronta;

    /** příznak spuštěného vlákna **/
    protected boolean běžící = false;

    /** zásobník vláken */
    private Thread vlákna[];

    /** počet nečinných vláken */
//    private int nečinnáVlákna;
//
//    private Object zámekPočtu = new Object();

    /** krátký class název implementující třídy */
    private String krátkýNázev;
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     *
     */
    public ASprávceUdálostí()
    {
    }



//== ABSTRAKTNÍ METODY =========================================================

    /**
     * potomci musí implementovat tuto metodu, aby mohly zpracovávat
     * herní události
     */
    protected abstract void zpracujUdalost(IHerniUdalost událost);
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================


    /**
     * @param početVláken požadovaný počet pracovních vláken
     */
    public final void initSprávceUdálostí(int početVláken)
    {
	krátkýNázev = this.getClass().getName().substring
                    (this.getClass().getName().lastIndexOf(".") + 1);
	log = Logger.getLogger(krátkýNázev);
	log.info("initObal - " + krátkýNázev);

	vstupníFronta = new FrontaUdálostí(krátkýNázev + "-in");

	// inicializace vláken
	vlákna = new Thread[početVláken];
	for (int i=0; i<početVláken; i++) {
	    vlákna[i] = new Thread(this, krátkýNázev + "-" + (i+1));
	    vlákna[i].setDaemon(true);
	    vlákna[i].start();
	}
    }

    /**
     * vypne aktivní vlákna
     */
    public void vypni () {
	běžící = false;
	if (vlákna != null) {
	    for (int i=0;i<vlákna.length;i++) {
		vlákna[i].interrupt();
	    }
	}
    }

    /**
     * zařazení události do fronty spravovaných herních událostí pro pozdější
     * zpracování aktivním vláknem
     */
    @Override
    public void spravujUdálost(IHerniUdalost událost) {
	vstupníFronta.pridej(událost);
    }

    /**
     * získá události z fronty událostí a zpracuje je.
     */
    @Override
    public void run() {
	IHerniUdalost událost;
	běžící = true;
	while (běžící) {
	    try {
		if ((událost = vstupníFronta.vyjmi()) != null) {
		    zpracujUdalost(událost);
		}
	    }
	    catch (InterruptedException e) {
	    }
	}
    }
//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTOVACÍ METODY A TŘÍDY ==================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        SprávceUdálostí inst = new SprávceUdálostí();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}
